#pragma once
#include "../Dispatcher.h"
#include <unordered_set>
#include <functional>
#include <thread>
class UDPClient;
struct OverlappedData;
struct sockaddr_in;
class UDPGroup : public Dispatcher
{
public:
	UDPGroup();
	~UDPGroup();

	bool Initialize();

	void Terminate();

	bool AddClient(UDPClient* client, int port);

	void RemoveClient(UDPClient* client);


	template <class _Fx, class _Types>
	void RegisterReceivedCallback(_Fx&& _Func, _Types&& _User) {
		onRecv = std::bind(_STD forward<_Fx>(_Func), _User, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
	}
	template <class _Fx>
	void RegisterReceivedCallback(_Fx&& _Func) {
		onRecv = std::bind(_STD forward<_Fx>(_Func), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
	}
	void UnregisterReceivedCallback() {
		onRecv = nullptr;
	}

private:

	static unsigned long _stdcall WorkerThread(void* lpParameter);

	bool BeginReceive(OverlappedData* data);

	void InsertContext(OverlappedData* data);

	void RemoveContext(OverlappedData* data);

	void RemoveOnMainThread(OverlappedData* data);
private:

	std::vector<void*> threadHandles;
	void* completionPort = nullptr;
	std::unordered_set<UDPClient*> clients;

	std::function<void(char* buffer, int len, sockaddr_in* remote, UDPClient* client)> onRecv;

	std::unordered_set<OverlappedData*> overlappedDataSet;
	std::mutex overlappedDataSetMux;
};

